import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_app/net_data/base/security_util.dart';

import 'log_interceptor.dart';

/// 封装的网络api
abstract class IApiClient {
  ///服务器连接成功
  static const int SERVER_SUCCESS = 10000;

  ///需要登录
  static const int NEED_LOGIN = 10002;

  ///业务层成功
  static const int API_SUCCESS = 1001;

  ///是否加密
  bool needEncrypt();

  ///域名
  String getBaseUrl();

  ///用户标示
  String userToken();

  ///处理需要登录
  void dealNeedLogin();

  ///开启网络接口日志
  bool needLog();

  ///loading处理
  void dealLoading(bool show);

  ///获取dio对象
  Dio? dio;

  Dio? getDio() {
    if (dio == null) {
      dio = Dio(BaseOptions(connectTimeout: 30000, baseUrl: getBaseUrl()));
      if (needLog()) {
        dio?.interceptors.add(MyLogsInterceptor(encrypt: needEncrypt()));
      }
      return dio;
    } else {
      return dio;
    }
  }

  ///获取头 heads
  Map<String, dynamic> getHeaders() {
    return {
      'Access-Token-Admin': userToken(),
    };
  }

  ///添加参数
  Future<Map<String, dynamic>> dealQAndSign(Map<String, dynamic> params,
      {bool skipEncrypt = false}) async {
    Map<String, dynamic> qAndSign = {};
    if (needEncrypt() && !skipEncrypt) {
      String q = await SecurityUtil.encrypt(
          params == null ? '{}' : json.encode(params));
      String sign = await SecurityUtil.doSign(q);
      qAndSign.putIfAbsent('sign', () => sign);
      qAndSign.putIfAbsent('q', () => q);
    } else {
      qAndSign.putIfAbsent('sign', () => "");
      qAndSign.putIfAbsent(
          'q', () => params == null ? '{}' : json.encode(params));
    }
    return qAndSign;
  }

  ///get请求
  getRequest(String url,
      {Map<String, dynamic>? params,
      Function? success,
      Function? error,
      bool toast = true,
      bool needLoading = true,
      Options? options,
      bool skipEncrypt = false}) async {
    Response? response;
    try {
      ///添加参数
      params = await dealQAndSign(params!, skipEncrypt: skipEncrypt);

      ///添加头
      Options options = Options(headers: getHeaders());

      ///是否加loading
      if (needLoading) {
        dealLoading(true);
      }

      ///获取得到数据
      response =
          await getDio()?.get(url, queryParameters: params, options: options);
      if (response != null && response.statusCode == 200) {
        ///请求成功，释放loading
        if (needLoading) {
          dealLoading(false);
        }
        var responseData = response.data;
        if (needEncrypt() && !skipEncrypt) {
          ///需要加密且不跳过加密
          responseData = await SecurityUtil.decrypt(response.data.toString());
        }

        Map<String, dynamic>? resultMap;
        if (responseData is Map) {
          print("HTTP: " + "resp data is map");
          resultMap = responseData.cast<String, dynamic>();
        } else {
          print("HTTP: " + "resp data is String");
          resultMap = json.decode(responseData);
        }
        //解析josn数据....
        if (resultMap != null) {
          var status = resultMap['status'];

          ///外层成功
          if (status == SERVER_SUCCESS) {
            var content = resultMap['content'];
            if (content == null) {
              _handError(2345, "数据格式异常",
                  errorCallback: error!, showToast: toast);
            } else {
              ///内层业务数据返回成功
              if (content['code'] == API_SUCCESS) {
                if (success != null) {
                  ///返回数据
                  success(content['data']);
                }
              } else {
                _handError(content['code'], content['codeDesc'],
                    errorCallback: error!, showToast: toast);
              }
            }
          } else {
            _handError(resultMap['status'], resultMap['msg'],
                errorCallback: error!, showToast: toast);
          }
        } else {
          _handError(7777, '数据格式异常', errorCallback: error!, showToast: toast);
        }
      } else {
        //请求失败
        if (needLoading) {
          dealLoading(false);
        }
        _handError(8888, '出错啦', errorCallback: error!, showToast: toast);
      }
    } on DioError catch (e) {
      if (needLoading) {
        dealLoading(false);
      }
      _handError(9999, '连接出问题了', errorCallback: error!, showToast: toast);
    } catch (e, stacktrace) {
      if (needLoading) {
        dealLoading(false);
      }
      _handError(6666, '程序出错了', errorCallback: error!, showToast: toast);
      debugPrint("***************异常信息***************：");
      debugPrint("异常信息:" + e.toString());
      debugPrint("异常信息位置:" + stacktrace.toString());
    }
  }

  void showToastMsg(String msg);

  // 返回错误信息
  Future? _handError(int code, String errorMsg,
      {Function? errorCallback, bool showToast = true}) {
    if (showToast) {
      showToastMsg(errorMsg ?? "出错了");
    }
    if (errorCallback != null) {
      errorCallback(code, errorMsg);
    }
    if (code == NEED_LOGIN) {
      dealNeedLogin();
    }
  }
}
